﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.IO;
using XemlUtilities;
using XemlUtilities.DataSet;
using Xeml.Sampling.Contracts;
using System.Threading.Tasks;

namespace Xid.Controls.IsaExport
{
    public partial class frmIsaExport : Form
    {
        /// <summary>
        /// description to be used for filling the 'state' column.
        /// </summary>
        enum fileState
        {
            [Description("Missing")]
            missing,
            [Description("Present")]
            present,
            [Description("unverified")]
            unverified
        };

        String _fileExtension = ".cdf"; // default extension
        String fileExtension
        {
            get { return this._fileExtension; }
            set
            {
                this._fileExtension = value;

                foreach (DataGridViewRow row in this.GVXemlFiles.Rows)
                {
                    row.Cells["fileextension"].Value = value;
                }
            }
        }

        public Xeml.Document.Contracts.IDocument _document { get; private set; }

        #region constructors
        public frmIsaExport(Xeml.Document.Contracts.IDocument document)
        {
            InitializeComponent();
            this._document = document;
            FillFileDataGrid(document);
        }
        #endregion constructors

        private void FillFileDataGrid(Xeml.Document.Contracts.IDocument doc)
        {
            // could be replaced by XemlUtilities.XemlDataSet.SampleMapping.GetChromatograms .. but it's a bit overkill to load a whole XemlDataSet
            using (SqlCommand cmd = new SqlCommand())
            using (cmd.Connection = new SqlConnection(XemlInteractiveDesigner.DataProviderSelectorForm.GetADataProvider(doc).provider.ConnectionString()))
            {
                cmd.Connection.Open();
                cmd.CommandText = @"SELECT Value as filename FROM Xeml.SampleMapping sm JOIN xeml.Document d ON d.id = sm.FK_Document WHERE d.XemlId = @XemlId and SubKey = 'Chromatogram'";
                cmd.Parameters.AddWithValue("@XemlID", doc.Id);
                cmd.Transaction = cmd.Connection.BeginTransaction(IsolationLevel.ReadUncommitted);
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    DataTable dt = new DataTable();

                    // add a column depicting if a file is present, unchecked or missing
                    DataColumn dc = new DataColumn("state");
                    dc.DefaultValue = fileState.unverified.ToString();
                    dt.Columns.Add(dc);

                    // add a column with the file path
                    DataColumn filePath = new DataColumn("filepath");
                    dt.Columns.Add(filePath);

                    // add a (hidden) column with the file extension and the original filename
                    DataColumn fileExtensionDc = new DataColumn("fileextension");
                    dt.Columns.Add(fileExtensionDc);
                    DataColumn oriFileName = new DataColumn("orifilename");
                    dt.Columns.Add(oriFileName);

                    dt.Load(reader);
                    GVXemlFiles.DataSource = dt;
                    // init the original file name column
                    foreach (DataGridViewRow row in GVXemlFiles.Rows)
                    {
                        row.Cells["orifilename"].Value = row.Cells["filename"].Value;
                    }
                    GVXemlFiles.Columns["orifilename"].Visible = false;
                    GVXemlFiles.Columns["fileextension"].Visible = false;
                    GVXemlFiles.CellValueChanged += new DataGridViewCellEventHandler(fileStateHandler);
                    GVXemlFiles.Sorted += new EventHandler(GVXemlFiles_Sorted);

                    // fill in the extension so we also trigger the events connected with it
                    foreach (DataGridViewRow row in GVXemlFiles.Rows)
                    {
                        row.Cells["fileextension"].Value = this.fileExtension;
                    }
                }
            }
        }

        void GVXemlFiles_Sorted(object sender, EventArgs e)
        {
            foreach (DataGridViewRow row in GVXemlFiles.Rows)
            {
                setFileStateColor(row);
            }
        }

        void fileStateHandler(object sender, DataGridViewCellEventArgs e)
        {
            setFileStateColor((DataGridViewRow)GVXemlFiles.Rows[e.RowIndex]);
        }

        void setFileStateColor(DataGridViewRow row)
        {
            // check the state of the file
            switch ((fileState)Enum.Parse(typeof(fileState), row.Cells["state"].Value.ToString()))
            {
                case fileState.unverified:
                    break;
                case fileState.missing:
                    row.DefaultCellStyle.BackColor = System.Drawing.Color.MediumVioletRed;
                    break;
                case fileState.present:
                    row.DefaultCellStyle.BackColor = System.Drawing.Color.MediumSpringGreen;
                    break;
            }

            // concat the filename with extension
            row.Cells["filename"].Value = row.Cells["orifilename"].Value.ToString() + row.Cells["fileextension"].Value.ToString();
        }

        private void BtnLinkFiles_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                List<String> files = folderBrowserDialog1.SelectedPath.GetFilesRecursively();
                Files filesChecker = new Files();
                IEnumerable<IGrouping<String, String>> duplicateFileGroups = filesChecker.getDuplicates(files);
                files = filesChecker.removeDuplicates(files);

                // for easy lookup later
                Dictionary<String, String> pathOf = files.ToDictionary<String, String>(x => Path.GetFileName(x));

                IEnumerable<DataGridViewRow> missingFiles = GVXemlFiles.Rows.Cast<DataGridViewRow>().Where(x => !files.Select(y => Path.GetFileName(y)).Contains<String>(x.Cells["filename"].Value.ToString())); // might be able to do this shorter?
                IEnumerable<DataGridViewRow> foundFiles = GVXemlFiles.Rows.Cast<DataGridViewRow>().Where(x => files.Select(y => Path.GetFileName(y)).Contains<String>(x.Cells["filename"].Value.ToString()));
                foreach (DataGridViewRow row in foundFiles)
                {
                    row.Cells["state"].Value = fileState.present;
                    row.Cells["filepath"].Value = Path.GetDirectoryName(pathOf[row.Cells["filename"].Value.ToString()]);
                }
                foreach (DataGridViewRow row in missingFiles)
                {
                    row.Cells["state"].Value = fileState.missing;
                }

                // check of the duplicated files are actually in the list
                if (duplicateFileGroups.Count() > 0)
                {
                    String msg = String.Empty;
                    foreach (var group in duplicateFileGroups)
                    {
                        foreach (var fileName in group)
                        {
                            msg += fileName + Environment.NewLine;
                        }
                        msg += Environment.NewLine;
                    }
                    MessageBox.Show(msg, "Duplicate files");
                }
            }
        }

        private void BtnCreateISAArchive_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.UseWaitCursor = true;
                this.Enabled = false;
                var tcs = new TaskCompletionSource<bool>();

                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        IDataProvider gmd = XemlInteractiveDesigner.DataProviderSelectorForm.GetADataProvider(_document).provider;
                        using (XemlDataSet xds = XemlDataSet.GetInstance(_document.Id, gmd))
                        using (XemlUtilities.ISA.IsaExporter exporter = new XemlUtilities.ISA.IsaExporter(xds.Document.First().XemlId, gmd.ConnectionString()))
                        using (Stream outfile = saveFileDialog1.OpenFile())
                        {
                            foreach (DataGridViewRow row in GVXemlFiles
                                .Rows
                                .Cast<DataGridViewRow>()
                                .Where(x => (fileState)Enum.Parse(typeof(fileState), x.Cells["state"].Value.ToString()) == fileState.present)
                            )
                            {
                                DataRow r = (row.DataBoundItem as DataRowView).Row;
                                String fileName = r.Field<string>("filename");
                                String filePath = r.Field<string>("filepath");
                                exporter.AddChromatogramFile(r.Field<string>("orifilename"), Path.Combine(filePath, fileName));
                            }
                            exporter.Write(xds, outfile);
                            tcs.SetResult(true);
                        }
                    }
                    catch (Exception ex)
                    {
                        tcs.SetException(ex);
                    }
                });
                tcs.Task.Wait();
                this.UseWaitCursor = false;
                this.Enabled = true;
                MessageBox.Show("Done!");
                if (tcs.Task.IsCanceled)
                {
                    Microsoft.SqlServer.MessageBox.ExceptionMessageBox box = new Microsoft.SqlServer.MessageBox.ExceptionMessageBox(tcs.Task.Exception);
                    box.Show(this);
                }
            }
        }



        private void BtnChangeExt_Click(object sender, EventArgs e)
        {
            frmInputExtension extensionDialog = new frmInputExtension();
            extensionDialog.textBox1.Text = fileExtension;

            if (extensionDialog.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                this.fileExtension = extensionDialog.textBox1.Text;
                if (this.fileExtension.Length > 0 && !this.fileExtension.StartsWith("."))
                {
                    this.fileExtension = "." + this.fileExtension;
                }
            }
        }

    }
}
